package cn.net.autocode.files.pdf;


import cn.net.autocode.files.pdf.entity.KeyWordPosition;
import cn.net.autocode.files.pdf.entity.SignPosition;
import cn.net.autocode.files.pdf.search.PdfBoxKeyWordSearch;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class PDFUtils {

    public static List<KeyWordPosition> searchKeywordPositions(String pdfFilePath, String keyword) throws IOException {
        File pdfFile = new File(pdfFilePath);
        PDDocument pdDocument = Loader.loadPDF(pdfFile);
        return PDFUtils.searchKeywordPositions(pdDocument,keyword);
    }

    public static List<KeyWordPosition> searchKeywordPositions(File pdfFile, String keyword) throws IOException {
        PDDocument pdDocument = Loader.loadPDF(pdfFile);
        return PDFUtils.searchKeywordPositions(pdDocument,keyword);
    }

    public static List<KeyWordPosition> searchKeywordPositions(PDDocument document, String keyword) throws IOException {
        List<KeyWordPosition> keyWordPositions = new ArrayList<>();
        int totalPages = document.getNumberOfPages();
        for(int pageNum=1;pageNum<=totalPages;pageNum++){
            List<KeyWordPosition> pageKeyWordPosition = searchKeywordPositions(document,keyword,pageNum);
            keyWordPositions.addAll(pageKeyWordPosition);
        }
        return keyWordPositions;
    }

    public static List<KeyWordPosition> searchKeywordPositions(PDDocument document, String keyword, int pageNum) throws IOException {
        StringBuffer keywordSb = new StringBuffer(keyword);
        PdfBoxKeyWordSearch pdfBoxKeyWordSearch = new PdfBoxKeyWordSearch(document, keywordSb, pageNum);
        return pdfBoxKeyWordSearch.getKeywordPositionList();
    }

    public static byte[] signPdf(PDDocument document, List<SignPosition> signPositions, File signImage) throws IOException {
        for(SignPosition signPosition:signPositions){
            int pageNum = signPosition.getPageNum();
            PDPage page = document.getPage(pageNum-1);
            // 加载签章图片
            PDImageXObject stampImage = PDImageXObject.createFromFileByContent(signImage,document);
            try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
                // 在指定位置绘制签章图片
                contentStream.drawImage(stampImage, signPosition.getRealX(), signPosition.getRealY(), signPosition.getWidth(), signPosition.getHeight());
            }
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        document.save(outputStream);
        return outputStream.toByteArray();
    }


    public static byte[][] splitPic(BufferedImage image, int cols, int rows, boolean isAverage, int[] picLens) throws IOException {
        float width = (float)image.getWidth();
        float height = (float)image.getHeight();
        if (picLens == null || picLens.length != 3) {
            picLens = splitStrategy(Float.valueOf(width).intValue(), Float.valueOf(height).intValue(), cols, rows, isAverage);
        }

        int firstWidth = picLens[0];
        int chunkWidth = picLens[1];
        int chunkHeight = picLens[2];

        int count = 0;
        int chunks = rows * cols;
        BufferedImage[] imgs = new BufferedImage[chunks];
        int indexX1 = 0;
        int indexX2 = 0;
        int indexY1 = 0;
        int indexY2 = 0;

        int i;
        for(int y = 0; y < rows; ++y) {
            for(i = 0; i < cols; ++i) {
                if (i == 0) {
                    indexX2 = firstWidth;
                    indexY2 = chunkHeight;
                    imgs[count++] = getImage(indexX1, firstWidth, indexY1, chunkHeight, image);
                } else {
                    indexX1 = indexX2;
                    indexX2 += chunkWidth;
                    imgs[count++] = getImage(indexX1, indexX2, indexY1, indexY2, image);
                }
            }

            indexY1 = indexY2;
            indexY2 += chunkHeight;
        }

        byte[][] arrays = new byte[imgs.length][];

        for(i = 0; i < imgs.length; ++i) {
            ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
            Throwable var20 = null;

            try {
                ImageIO.write(imgs[i], "png", byteOutputStream);
                arrays[i] = byteOutputStream.toByteArray();
            } catch (Throwable var29) {
                var20 = var29;
                throw var29;
            } finally {
                if (var20 != null) {
                    try {
                        byteOutputStream.close();
                    } catch (Throwable var28) {
                        var20.addSuppressed(var28);
                    }
                } else {
                    byteOutputStream.close();
                }

            }
        }
        return arrays;
    }

    public static int[] splitStrategy(int width, int height, int cols, int rows, boolean isAverage) {
        int[] lens = new int[3];
        if (width < cols) {
            lens[0] = 10;
            lens[1] = 1;
            lens[2] = height;
            return lens;
        } else {
            int ratio;
            if (cols > 2 && !isAverage) {
                if (cols <= 5) {
                    ratio = 40;
                } else if (cols <= 11) {
                    ratio = 30;
                } else if (cols <= 31) {
                    ratio = 20;
                } else {
                    ratio = 15;
                }

                lens[1] = width * (100 - ratio) / 100 / cols;
                if (lens[1] <= 0) {
                    lens[1] = 1;
                }

                lens[2] = height / rows;
                lens[0] = width - lens[1] * (cols - 1);
                return lens;
            } else {
                lens[1] = width / cols;
                lens[2] = height / rows;
                lens[0] = width - lens[1] * (cols - 1);
                return lens;
            }
        }
    }

    private static BufferedImage getImage(int indexX1, int indexX2, int indexY1, int indexY2, BufferedImage image) {
        int chunkWidth = indexX2 - indexX1;
        int chunkHeight = indexY2 - indexY1;
        int type = image.getType() == 0 ? 2 : image.getType();
        BufferedImage resetImage = new BufferedImage(chunkWidth, chunkHeight, type);
        Graphics2D gr = resetImage.createGraphics();
        gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, indexX1, indexY1, indexX2, indexY2, null);
        gr.dispose();
        return resetImage;
    }


}
